#define _GNU_SOURCE
#include "daemon_sub_process.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/reboot.h>
#include <signal.h>
#include <log/log.h>

SubProcess *daemon_sub_process_init(char *cmd_param)
{
    // 申请内存
    SubProcess *sp = (SubProcess *)malloc(sizeof(SubProcess));
    // 初始化sp属性
    sp->pid = -1;
    sp->cmd_param = cmd_param;
    sp->fail_count = 0;
    return sp;
}

/**
 * @brief 检查并启动子进程
 */
int daemon_sub_process_checkStart(SubProcess *sp)
{
    // 检查子进程是否已经启动，如果已经启动，则直接返回
    int status ;
    // waitpid不会真等子进程结束，如果子进程还在运行中，waitpid会立即返回0
    // 如果子进程已结束，将进程结束时的状态保存到status中
    if (sp->pid > 0 && waitpid(sp->pid, &status, WNOHANG) == 0) 
    {
        log_debug("进程(%s)正在运行中 ...", sp->cmd_param);
        // 子进程还在运行
        return 0;
    }
    // 子进程已经退出
    if ( status == -1 )
    {
        // 子进程异常退出
        sp->fail_count++;
        if (sp->fail_count > MAX_FAIL_COUNT)
        {
            // 重启系统
            reboot(RB_AUTOBOOT);
        }
    }

    // 创建子进程
    sp->pid = fork();
    if (sp->pid == 0)
    {
        log_debug("子进程(%d)执行程序", sp->cmd_param);
        // 子进程
        char *argv[] = {EXE_PATH, sp->cmd_param, NULL};
        execve(EXE_PATH, argv, NULL);
        log_error("execve 程序(%s) error", sp->cmd_param);
        _exit(EXIT_FAILURE);
    }
    return 0;   
}

/**
 * @brief 关闭子进程
 */
void daemon_sub_process_colse(SubProcess *sp)
{
    // 杀死子进程
    kill(sp->pid, SIGTERM);
    // 等待子进程退出
    waitpid(sp->pid, NULL, 0);
    // 释放内存
    free(sp);
}
